<?php

/**
 * Created by Unknown
 *
 *            ┏┓　　  ┏┓+ +
 *           ┏┛┻━━━━━┛┻┓ + +
 *           ┃         ┃ 　
 *           ┃   ━     ┃ ++ + + +
 *          ████━████  ┃+
 *           ┃　　　　　 ┃ +
 *           ┃　　　┻　　┃
 *           ┃　　　　　 ┃ + +
 *           ┗━┓　　　┏━┛
 *             ┃　　　┃　　　　
 *             ┃　　　┃ + + + +
 *             ┃　　　┃    Code is far away from bug with the alpaca protecting
 *             ┃　　　┃ + 　　　　        神兽保佑,代码无bug
 *             ┃　　　┃
 *             ┃　　　┃　　+
 *             ┃     ┗━━━┓ + +
 *             ┃         ┣┓
 *             ┃ 　　　　　┏┛
 *             ┗┓┓┏━━┳┓┏━┛ + + + +
 *              ┃┫┫  ┃┫┫
 *              ┗┻┛  ┗┻┛+ + + +
 * User: MotherFucker
 * Date: 2016-07-05
 * Time: 下午 3:19
 */

use Yaf\Controller_Abstract;
use Yaf\Session;
use Yaf\Registry;

class ErrorController extends Controller_Abstract
{
    public function errorV1Action($exception){
        var_dump(2);exit;
        $trace_arr = $exception->getTrace();
        $trace_array = [];
        //匹配获取报错的控制器
        foreach ($trace_arr as $value){
            if(!isset($value['file'])){
                $trace_array = $value;
            }
        }

        // 获取报错代码所在的控制器名与action名
        $func_name = str_replace('Action', 'Back', $trace_array['function']);
        $class_name = strtolower(str_replace('Controller', '', $trace_array['class']));

        // 兼容phpunit
        // func_name若在开头带有test，且带有With，且不是Back结尾的，表示这是一个phpunit的用例，需要取出test与With之间的字符串来做为func_name
        $func_name = (stripos($func_name, 'test') === 0 && strrpos($func_name, 'Back') === false) ?
            ((strpos($func_name, 'With') === false ?
                    substr($func_name, (stripos($func_name, 'test') + strlen('test'))) :
                    substr($func_name, (stripos($func_name, 'test') + strlen('test')), (stripos($func_name, 'With') - strlen('With')))
                ) . 'Back') :
            $func_name;
        // class_name是一个命名空间（包含\），且是test结尾的，就表示他是个phpunit过来的类，此时需要获取最后一个\到test这个词之间的字符串来作为class_name
        $class_name = strrpos($class_name, 'test') + strlen('test') === strlen($class_name) ?
            substr($class_name, strrpos($class_name, '\\') + 1, (strlen($class_name) - strrpos($class_name, '\\') - strlen('test') - 1)) :
            $class_name;
        list($func_name, $parameters) = \Common\Util::getParam4Proto($class_name, $func_name);

        // 根据错误代码所在的控制器与action来查找对应的返回协议类，并实例化
        $proto_class_name = '\\Proto\\'.ucfirst($class_name).'\\'.$func_name.'';
        $proto_class = new $proto_class_name();

        //递归获取当前返回协议中所有变量，为Util中的return_arr赋值
        \Common\Util::tailRecursion($parameters);
        \Common\Util::$proto_file_name=ucfirst($class_name);

        //判断callinfomes是否存在
        if(strrpos($parameters['value'],"callinfomes") === false){
            $new_parameters = [
                'stateenum'=> $exception->getCode(),
                'err'=> $exception->getMessage()
            ];
        }else{
            $new_parameters = [
                'callinfomes' => [
                    'stateenum'=> $exception->getCode(),
                    'err'=> $exception->getMessage()
                ]
            ];
        }


        // 调用赋值方法，将此处的值传入，调用对应类的方法，修改其属性
        $proto = \Common\Util::protoResponse($proto_class, $new_parameters);

        // 返回proto协议
        return $this->getResponse()->setBody($proto->serializeToJsonString());
    }

    public function errorAction($exception){


        $is_json = false;
        //接口与ajax请求，设置response header为json

        if($this->getRequest()->isXmlHttpRequest() && strpos($this->getRequest()->getRequestUri(), 'admin') ===false ){
            $is_json = true;
        }

        if($is_json === false){

            $is_admin = strpos($this->getRequest()->getRequestUri(), 'admin') !== false ? true : false;

            if(strpos($this->getRequest()->getRequestUri(), 'logout') !== false){
                $redirect_url = $is_admin === true ? '/admin/login/index' :
                   '/member/login' ;
            }else{

                if($this->getRequest()->getServer('HTTP_REFERER') == null){
                    $access_list = $is_admin === true ? json_decode(Session::getInstance()->get("access_list"), true) :
                        '/';
                    $redirect_url = is_array($access_list) ? current($access_list) : $access_list;
                }else{
                    $redirect_url = $this->getRequest()->getServer('HTTP_REFERER');
                }
            }

            //前端抛错页面
            if($is_admin === false){
//                var_dump($redirect_url);exit;
                $message = json_decode($exception->getMessage(), true);
                $content = [
                    'url' => $exception->getCode() != '400' ? $redirect_url :
                        '/admin/user/login?redirect_url=' . $redirect_url,
                    'message' => is_null($message) ? $exception->getMessage() :
                        (isset($message['message']) ? $message['message'] : 'exception的message不是个有效数组'),
                    'title' => is_null($message) ? '' :
                        (isset($message['title']) ? $message['title'] : 'exception的message不是个有效数组')
                ];
                $this->getView()->assign(
                    'content',
                    $content
                );
                //手机端
                if(Registry::get("user_log_info")['is_mobile'] === true){
                    $this->display('mobiletips');
                }else{
                    $this->display('errorfrontend');
                }
            }
            //后台抛错页面
            else{
                $message = json_decode($exception->getMessage(), true);
                if(strpos($this->getRequest()->getRequestUri(), 'login') !== false){
                    $code = 10001;
                }else{
                    $code = $exception->getCode();
                }
                $content = [
                    'url' => $exception->getCode() != '400' ? $redirect_url :
                        '/admin/user/login?redirect_url=' . $redirect_url,
                    'message' => is_null($message) ? $exception->getMessage() :
                        (isset($message['message']) ? $message['message'] : 'exception的message不是个有效数组'),
                    'title' => is_null($message) ? '' :
                        (isset($message['title']) ? $message['title'] : 'exception的message不是个有效数组')
                ];
                Registry::get("error_log")->addAlert('',['error_log' => $content]);
                return $this->getResponse()->setBody(json_encode(['code' => $code, 'msg' => $content]));
            }
        }else{
            $trace_arr = $exception->getTrace();
            $trace_array = [];
            //匹配获取报错的控制器
            foreach ($trace_arr as $value){
                if(!isset($value['file'])){
                    $trace_array = $value;
                }
            }

            // 获取报错代码所在的控制器名与action名
            $func_name = str_replace('Action', 'Back', $trace_array['function']);
            $class_name = strtolower(str_replace('Controller', '', $trace_array['class']));

            // 兼容phpunit
            // func_name若在开头带有test，且带有With，且不是Back结尾的，表示这是一个phpunit的用例，需要取出test与With之间的字符串来做为func_name
            $func_name = (stripos($func_name, 'test') === 0 && strrpos($func_name, 'Back') === false) ?
                ((strpos($func_name, 'With') === false ?
                        substr($func_name, (stripos($func_name, 'test') + strlen('test'))) :
                        substr($func_name, (stripos($func_name, 'test') + strlen('test')), (stripos($func_name, 'With') - strlen('With')))
                    ) . 'Back') :
                $func_name;
            // class_name是一个命名空间（包含\），且是test结尾的，就表示他是个phpunit过来的类，此时需要获取最后一个\到test这个词之间的字符串来作为class_name
            $class_name = strrpos($class_name, 'test') + strlen('test') === strlen($class_name) ?
                substr($class_name, strrpos($class_name, '\\') + 1, (strlen($class_name) - strrpos($class_name, '\\') - strlen('test') - 1)) :
                $class_name;
            list($func_name, $parameters) = \Common\Util::getParam4Proto($class_name, $func_name);

            // 根据错误代码所在的控制器与action来查找对应的返回协议类，并实例化
            $proto_class_name = '\\Proto\\'.ucfirst($class_name).'\\'.$func_name.'';
            $proto_class = new $proto_class_name();

            //递归获取当前返回协议中所有变量，为Util中的return_arr赋值
            \Common\Util::tailRecursion($parameters);
            \Common\Util::$proto_file_name=ucfirst($class_name);

            //判断callinfomes是否存在
            if(strrpos($parameters['value'],"callinfomes") === false){
                $new_parameters = [
                    'stateenum'=> $exception->getCode(),
                    'err'=> $exception->getMessage()
                ];
            }else{
                $new_parameters = [
                    'callinfomes' => [
                        'stateenum'=> $exception->getCode(),
                        'err'=> $exception->getMessage()
                    ]
                ];
            }


            // 调用赋值方法，将此处的值传入，调用对应类的方法，修改其属性
            $proto = \Common\Util::protoResponse($proto_class, $new_parameters);

            // 返回proto协议
            return $this->getResponse()->setBody($proto->serializeToJsonString());
        }
    }
}